package levels;

import java.util.ArrayList;

import editor.Level;

import math.*;

public class PathGrid 
{
	private ArrayList<ArrayList<Node>> tiles;
	
	public PathGrid( Level lev )
	{
		tiles = new ArrayList<ArrayList<Node>>();
		
		for( int y = 0; y < lev.getHeight(); y++ )
		{
			tiles.add( new ArrayList<Node>() );
			
			for( int x = 0; x < lev.getWidth(); x++ )
			{
				tiles.get( y ).add( new Node( fromGridToWorld( x, y ), lev.isOccupiedTile( x, y ) ) );
			}
		}
	}
	
	public ArrayList<ArrayList<Node>> getTiles()
	{
		return tiles;
	}
	
	public int getTileWidth()
	{
		return getTiles().get(0).size();
	}
	
	public int getTileHeight()
	{
		return getTiles().size();
	}
	
	public Node getContainingTile( Vector2D point )
	{
		Vector2D v = fromWorldToGrid( point );
		
		return tiles.get( (int)v.getY() ).get( (int)v.getX() );
	}
	
	/**
	 * Return the max 8 tiles adjacent to this one
	 * @param t
	 * @return
	 */
	public ArrayList<Node> getAdjacentTiles(Node t)
	{
		//needs to be optimized to remove duplicates
		ArrayList<Node> ts = new ArrayList<Node>();

		Vector2D v = fromWorldToGrid( t.getPosition() );
		
		//go clockwise starting from left adj tile
		ts.add( tiles.get( (int)v.getY() ).get( (int)v.getX() - 1 ) );
		ts.add( tiles.get( (int)v.getY() - 1 ).get( (int)v.getX() ) );
		ts.add( tiles.get( (int)v.getY() ).get( (int)v.getX() + 1 ) );		
		ts.add( tiles.get( (int)v.getY() + 1 ).get( (int)v.getX() ) );
		
		/* These are diagonal tiles
		ts.add( tiles.get( (int)v.getY() - 1 ).get( (int)v.getX() - 1 ) );
		ts.add( tiles.get( (int)v.getY() - 1 ).get( (int)v.getX() + 1 ) );
		ts.add( tiles.get( (int)v.getY() + 1 ).get( (int)v.getX() - 1 ) );
		ts.add( tiles.get( (int)v.getY() + 1 ).get( (int)v.getX() - 1 ) );
		 */
		
		return ts;
	}
	
	
	public static int getAngle( Vector2D from, Vector2D to )
    {
            from = fromWorldToGrid( from );
            to = fromWorldToGrid( to );
            
            int xC = (int)( from.getX() - to.getX() );
            int yC = (int)( from.getY() - to.getY() );
            
            if( xC == 0 && yC == -2 )
                    return 0;
            else if( ( xC == 1 || xC == 0 ) && yC == -1  )
                    return 45;
            else if( xC == 1 && yC == 0 )
                    return 90;
            else if( ( xC == 1 || xC == 0 ) && yC == 1  )
                    return 135;
            else if( xC == 0 && yC == 2  )
                    return 180;
            else if( ( xC == -1 || xC == 0 ) && yC == 1  )
                    return 225;
            else if( xC == -1  && yC == 0  )
                    return 270;
            else
                    return 315;
    }
	
	/**
     * @param v The vector in world coordinates to change
     * @return A vector on the grid in world coordinates
     */
    public static Vector2D fromWorldToWorldOnGrid( Vector2D v )
    {
           double x = v.getX() - v.getX() % 32 + 16;
           double y = v.getY() - v.getY() % 32 + 16;
           
           return new Vector2D( x, y );
    }

	/**
     * @param v The vector in world coordinates
     * @return A vector in grid coordinates
     */
    public static Vector2D fromWorldToGrid( Vector2D v )
    {
    	 double x = ( v.getX() - v.getX() % 32 + 16 ) / 32;
         double y = ( v.getY() - v.getY() % 32 + 16 ) / 32;

         return new Vector2D( x, y );
    }
    
    /**
     * @param x1 The x value of a grid coordinate
     * @param y1 The y value of a grid coordinate
     * @return The world coordinates of the grid
     */ 
    public static Vector2D fromGridToWorld( int x1, int y1 )
    {
    	double x = x1 * 32 + 16;
        double y = y1 * 32 + 16;
        
        return new Vector2D( x, y );
    }
    
    /**
     * @param v The vector in grid coordinates
     * @return The world coordinates of the grid
     */
    public static Vector2D fromGridToWorld( Vector2D v )
    {
    	double x = v.getX() * 32 + 16;
        double y = v.getY() * 32 + 16;
        
        return new Vector2D( x, y );
    }
}
